# -*- coding: utf-8 -*-
'''
Copyright(C) 2013 "Kevin Xu <ssonxu@gmail.com>"

This file is part of acqu-center.

acqu-center is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

acqu-center is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with acqu-center.  If not, see <http://www.gnu.org/licenses/>.
'''
#
#--------------------------------------------------------------------
# Data Structures
#--------------------------------------------------------------------
# label: { 
#     url: url,
#     stuffs: 
#     {
#        item : { pattern:pattern, message:message, expression:[lambda, p1, p2], matched:[ val, ref ] },
#        ...
#     },
#     topic: @topic
# }
#
#---------------------------------------------------------------------
# Class Structures
#---------------------------------------------------------------------
# ** box   
#       {
#           @url:url,
#           @stuffs: {
#               @@item:stuff,
#               ...
#           },
#       }
#
# ** sutff
#       { 
#           @pattern:pattern
#           @message:message
#           @expression: [ lambda, p1, p2 ]
#           @matched: [ val, ref ]}
#       }
#
import logging
from Predef import Predef as PRE
from google.appengine.ext import ndb
from parser import parser as ROCK


class Stuff(ndb.Model):
    date = ndb.DateTimeProperty(required=True, auto_now_add=True)
    pattern = ndb.StringProperty(required=True, indexed=False)
    message = ndb.StringProperty(required=True, indexed=False)

    expression = ndb.StringProperty(required=True, indexed=False)
    val = ndb.StringProperty(default='0', indexed=False)
    ref = ndb.StringProperty(default='0', indexed=False)
    p1 = ndb.StringProperty(default='0', indexed=False)
    p2 = ndb.StringProperty(default='0', indexed=False)


    ############
    # process
    ############
    def ID(self):
        return self.date.strftime('%Y%m%d%H%M%S%f')

    def isMatched(self):
        lam = u"lambda val,ref,p1,p2:%s" % self.expression
        return eval(lam)(self.val, self.ref, self.p1, self.p2)

    def keepref(self):
        self.ref = self.val

class Box(ndb.Model):
    ############
    # Initialize
    ############
    label = ndb.StringProperty(required=True)
    url = ndb.StringProperty(default=PRE.url_)
    description = ndb.StringProperty(indexed=False,default='')
    catagory = ndb.StringProperty(default='')
    stuffs = ndb.StructuredProperty(Stuff, repeated=True, indexed=False)
    isRunning = ndb.BooleanProperty(default=False)

    ############
    # process
    ############
    def ID(self):
        return self.key.id()

    def lauchIt(self):
        self.isRunning=True
        self.put()

    def drawbackIt(self):
        self.isRunning=False
        self.put()

    def flush(self):
        for k in self.stuffs:
            if k.isMatched():
                k.keepref()

    def hasUpdate(self):
        for k in self.stuffs:
            if k.isMatched():
                return True
        return False

    def report(self,isReportAll=False, isSkipMatch=False, isHTML=False):
        Content=[]
        if isSkipMatch or self.hasUpdate():
            for k in self.stuffs:
                if isSkipMatch or isReportAll or k.isMatched():
                    c = k.message.format(k.val,k.ref)
                    Content.append(u"<p>{}</p>".format(c)
                             if isHTML else c)

        if len(Content)>0:
            # add desciption and header
            if isHTML:
                return u'<p>{}</p>-----------------------<p>{}</p>-----------------------<p>Source: {}</p>-----------------------'.format(
                    self.label,u'\n'.join(Content), self.url)
            else:
                return u'{}\n-----------------------\n{}\n-----------------------\nSource: {}\n-----------------------'.format(
                    self.label,u'\n'.join(Content), self.url)

        return ''

    ############
    # class
    ############
    @classmethod
    def getMenu(cls, Running=False):
        res=[]
        ll=cls.listBoxes(Running=True)
        for x in ll:
            res.append(u"{}. {} - {}".format(ll.index(x), x.label, x.description))

        return u'\n'.join(res)

    @classmethod
    def listBoxes(cls, Running=False, Limit=None, Offset=0):
        query = cls.query(cls.isRunning == Running).order(cls.label)
        return query.fetch(limit=Limit, offset=Offset)

    @classmethod
    def getBoxByNo(cls, n):
        query=cls.listBoxes(Running=True, Limit=1, Offset=n )
        if len(query)>0:
            return query[0]
        else:
            return None

    @classmethod
    def getBox(cls, label):
        query = cls.query(cls.label == label)
        return query.get()

    @staticmethod
    def getBoxByID(ID):
        return ndb.Key(Box, ID).get()

    #@classmethod
    #def delBox(cls, label):
    #    query = cls.query(cls.label == label)
    #    return query.get().key.delete()

    @classmethod
    def delBoxByID(cls, ID):
        b = Box.getBoxByID(ID)
        if b is not None:
            return b.key.delete()
        return None
        
    @classmethod
    def rockMe(cls):
        for x in cls.listBoxes(Running=True):
            x.flush()
            ROCK(x).run()
            x.put()

